extends fpga
extends simulation
extends systemverilog

snippet al      "always clk"
always @ (posedge ${1:clk})
begin
    ${2:/*code*/}
end
endsnippet

snippet in      "input       port"
input                       ${1:port},
endsnippet

snippet inb     "input      [MSB:0] port"
input        [${1:MSB}:00]        ${2:port},
endsnippet

snippet our    "output port"
output  reg                 ${1:port},
endsnippet

snippet ourb    "reg  [MSB:0] variable"
output  reg  [${1:MSB}:00]        ${2:port},
endsnippet

snippet ouw    "wire  variable"
output                      ${1:variable},
endsnippet

snippet ouwb    "wire [MSB:0] variable"
output       [${1:MSB}:00]        ${2:variable},
endsnippet

#reg
snippet reg
reg                         ${1:outport};
endsnippet

snippet regb
reg     [${1:MSB}:00]             ${2:outport};
endsnippet

#wire
snippet wi      "wire   port"
wire                        ${1:port};
endsnippet

snippet wib     "wire   [MSB:0] port"
wire    [${1:MSB}:00]             ${2:port};
endsnippet

snippet mem     "reg [7:0] mem[0:255]"
reg     [7:0]           mem[0:255];
endsnippet

#system function or task
#readmemh
snippet readmemh    "read file data to memory"
reg     [7:0]   DataMem[0:31];
$readmemh("${1:/*data.txt*/}",${2:/*DataMem*/});
endsnippet

#test
snippet st  "three state machine"
reg     [3:0]           current_state, next_state;
reg     [15:0]          state_cnt;
localparam              sIdle_state = 0;
//-------------------------------------------------------------------------
//next_state滞后于current_state一个周期
//-------------------------------------------------------------------------
always @ (posedge ${1:clk} or negedge ${2:rst})         // build the state flops
begin
    if(~rst)
        current_state       <= ${3:sIdle_state};
    else
        current_state       <= ${4:next_state};
end

//-------------------------------------------------------------------------
//second.state transfer
//-------------------------------------------------------------------------
always @ ( * )      //state machine, block assign
begin
    case(current_state)
        sIdle_state:
        begin
            if(/*xx*/)
                next_state = /*xx_state*/;
            else
                next_state = current_state;
        end
        default: next_state = sIdle_state;
    endcase
end

//-------------------------------------------------------------------------
//three.output
//-------------------------------------------------------------------------
always @ (posedge $1 or negedge $2)     //output
begin
    if(~rst)
    begin
    end
    else
    begin
        case(next_state)
            sIdle_state:
            begin
            end
            default:
            begin
            end
        endcase
    end
end

/*
 * 状态跳转计数器
 */
always @ (posedge clk or negedge rst)
begin
    if(~rst)
        state_cnt <= 0;
    else if (next_state != current_state)
        state_cnt <= 0;
    else
        state_cnt <= state_cnt + 1'b1;
end
endsnippet

snippet keep_altera    "altera format, statement end"
/* synthesis keep */
endsnippet

snippet keep_xilinx    "xilinx format, statement start"
(* KEEP = "TRUE" *)
endsnippet

snippet state   "one hot encode machine state"
localparam              IDLE    = 0;
localparam              OVER    = 1;
(* KEEP = "TRUE" *)reg     [OVER:00]       cs = 'd1, ns = 'd1;
reg     [15:00]         state_cnt = 0;
reg     [15:00]         state_cnt_n = 0;

// synthesis translate_off
reg [127:0] cs_STRING;
always @(*)
begin
    case(1'b1)
        cs[IDLE]: cs_STRING = "IDLE";
        cs[HEAD]: cs_STRING = "HEAD";
        default: cs_STRING = "XXXX";
    endcase
end
// synthesis translate_on

always @(posedge clk)
begin
	cs <= ns;
end

always @(*)
begin
    ns = 'd0;
    case(1'b1)
        cs[IDLE]:
        begin
            if(/*condition*/)
                ns[/*next_state*/] = 1'b1;
            else
                ns[IDLE] = 1'b1;
        end
        cs[HEAD]:
        begin
            if(/*condition*/)
                ns[/*next_state*/] = 1'b1;
            else
                ns[HEAD] = 1'b1;
        end
        default:
            ns[IDLE] = 1'b1;
    endcase
end

always @ (posedge clk)
begin
	state_cnt <= state_cnt_n;
end

always @ (*)
begin
    if (cs != ns)
        state_cnt_n = 0;
    else
        state_cnt_n = state_cnt + 1'b1;
end
endsnippet

snippet generate_for "" 
genvar i;
generate 
	for(i = 0; i < ${1:N}; i = i + 1) 
	begin
		${2:statement}
	end
endgenerate
endsnippet

snippet generate_if ""
parameter USE_CASE = 0;

generate 
	if(USE_CASE)
	begin
		// instantiation
	end
	else
	begin
		// instantiation
	end

endgenerate
endsnippet

snippet generate_case ""
generate 
	case(${1:condition})
		1'b0:
		begin
			// instantiation
		end
		1'b1:
		begin
			// instantiation
		end
		default:
		begin
			// instantiation
		end
	endcase
endgenerate
endsnippet

snippet dump "dump vcd file"
initial
begin
	$dumpfile("${1:file}.vcd");
	$dumpvars(0, ${2:module});
end
endsnippet

